package com.jrx.anytxn.transaction.handler.impl;

import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnArgumentException;
import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.customer.entity.CmCustomerExtInfo;
import com.jrx.anytxn.customer.entity.CmCustomerFirstLevel;
import com.jrx.anytxn.customer.entity.CmCustomerSecondLevel;
import com.jrx.anytxn.customer.mapper.ext.ExtCmCustomerExtInfoMapper;
import com.jrx.anytxn.customer.service.ICustomerService;
import com.jrx.anytxn.param.dto.aviator.RuleMatchReq;
import com.jrx.anytxn.param.dto.system.SystemParameterRes;
import com.jrx.anytxn.param.entity.PrAmortMethod;
import com.jrx.anytxn.param.entity.PrChannelTable;
import com.jrx.anytxn.param.entity.PrInterestTable;
import com.jrx.anytxn.param.entity.PrOrganizationTable;
import com.jrx.anytxn.param.entity.PrPenaltyRateTable;
import com.jrx.anytxn.param.entity.PrProductTable;
import com.jrx.anytxn.param.service.aviator.IAviatorService;
import com.jrx.anytxn.param.service.product.IAmortMethodService;
import com.jrx.anytxn.param.service.product.IInterestTableService;
import com.jrx.anytxn.param.service.product.IPrPenaltyRateTableService;
import com.jrx.anytxn.param.service.product.IProductTableService;
import com.jrx.anytxn.param.service.system.IChannelTableService;
import com.jrx.anytxn.param.service.system.IOrganizationTableService;
import com.jrx.anytxn.param.service.system.ISystemParameterService;
import com.jrx.anytxn.param.utils.BizTypeProducts;
import com.jrx.anytxn.transaction.bean.PromotionLabelBean;
import com.jrx.anytxn.transaction.constant.TransBizConstant;
import com.jrx.anytxn.transaction.constant.TransErrMsgConstant;
import com.jrx.anytxn.transaction.dto.loan.MatchingAmortMethodReq;
import com.jrx.anytxn.transaction.dto.loan.MatchingAmortMethodRes;
import com.jrx.anytxn.transaction.dto.loanRelationInfo.AmortMethodRes;
import com.jrx.anytxn.transaction.dto.loanRelationInfo.LoanElementQueryReq;
import com.jrx.anytxn.transaction.dto.loanRelationInfo.LoanElementQueryRes;
import com.jrx.anytxn.transaction.dto.loanRelationInfo.LoanRateQueryReq;
import com.jrx.anytxn.transaction.dto.loanRelationInfo.LoanRateQueryRes;
import com.jrx.anytxn.transaction.handler.ILoanRelationInfoHandler;
import com.jrx.anytxn.transaction.service.IPromotionService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 贷款相关信息handler实现
 *
 * @author : zhenghaopu
 * 2019/11/21
 */
@Component
public class LoanRelationInfoHandlerImpl implements ILoanRelationInfoHandler {

    private static final Logger logger = LoggerFactory.getLogger(LoanRelationInfoHandlerImpl.class);

    @Autowired
    private IProductTableService productTableService;
    @Autowired
    private IInterestTableService interestTableService;
    @Autowired
    private IPrPenaltyRateTableService prPenaltyRateTableService;
    @Autowired
    private IAviatorService aviatorService;
    @Autowired
    private ICustomerService customerService;
    @Autowired
    private IOrganizationTableService organizationTableService;
    @Autowired
    private ISystemParameterService systemParameterService;
    @Autowired
    private IChannelTableService channelTableService;
    @Autowired
    private IAmortMethodService amortMethodService;
    @Autowired
    private IPrPenaltyRateTableService penaltyRateTableService;
    @Autowired
    private IPromotionService promotionService;
    @Autowired
    private ExtCmCustomerExtInfoMapper extCmCustomerExtInfoMapper;


    @Override
    public LoanElementQueryRes queryLoanElement(LoanElementQueryReq loanElementQueryReq) throws Exception {

        //验证产品id与贷款类型是否同时为空
        if (StringUtils.isBlank(loanElementQueryReq.getProductId()) && StringUtils.isBlank(loanElementQueryReq.getProductType())) {
            logger.error(TransErrMsgConstant.LOAN_ELEMENT_PARAM_ERROR);
            throw new TxnArgumentException(TxnRespCode.ERROR.getUserTips());
        }

        //构建返回
        LoanElementQueryRes loanElementQueryRes = new LoanElementQueryRes();

        PrChannelTable channelTable = channelTableService.getChannelTableByChannelIdAndStatus(TransBizConstant.YES_FLAG, loanElementQueryReq.getChannel(), loanElementQueryReq.getTenantId());
        //判断产品id是否为空 为空则通过规则获取
        if (StringUtils.isBlank(loanElementQueryReq.getProductId())) {
            //接口没有上传产品id  通过规则查询产品id
            loanElementQueryReq.setProductId(getProductIdByRule(loanElementQueryReq, channelTable.getOrganizationId()));
        }
        PrProductTable product = productTableService.findProByProIdAndOrgId(loanElementQueryReq.getProductId(),
                channelTable.getOrganizationId(), loanElementQueryReq.getTenantId());
        //产品编码
        loanElementQueryRes.setProductId(product.getProductId());
        //产品名称
        loanElementQueryRes.setProductName(product.getChineseName());
        //最大金额
        loanElementQueryRes.setMaxAmount(product.getMaxAmount());
        //最小金额
        loanElementQueryRes.setMinAmount(product.getMinAmount());
        //贷款类型
        loanElementQueryRes.setProductType(product.getTableType());
        //最小剩余本金
        loanElementQueryRes.setMinRemainPrincipal(product.getMinRemainPrincipal());
        //主动还款，最小还款金额
        loanElementQueryRes.setMinRepayAmount(product.getMinRepayAmount());
        //是否允许联合贷标志
        loanElementQueryRes.setAllowJointFlag(product.getAllowJointFlag());


        if (StringUtils.isNotBlank(loanElementQueryReq.getUserId())) {
            logger.debug("校验还款方式，期数");
            MatchingAmortMethodReq matchingAmortMethodReq = new MatchingAmortMethodReq();
            matchingAmortMethodReq.setChannel(loanElementQueryReq.getChannel());
            matchingAmortMethodReq.setUserId(loanElementQueryReq.getUserId());
            matchingAmortMethodReq.setTenantId(loanElementQueryReq.getTenantId());
            matchingAmortMethodReq.setProductId(loanElementQueryReq.getProductId());
            MatchingAmortMethodRes matchingAmortMethodRes = this.matchingAmortMethodHandle(matchingAmortMethodReq);
            // 还款方式和期数
            loanElementQueryRes.setAmortMethodRes(matchingAmortMethodRes.getAmortMethodResList());
        }
        return loanElementQueryRes;
    }

    @Override
    public LoanRateQueryRes queryLoanRate(LoanRateQueryReq loanRateQueryReq) throws TxnException {
        //构建返回信息
        LoanRateQueryRes loanRateQueryRes = new LoanRateQueryRes();
        //验证客户是否存在
        logger.info("查询客户信息，客户id[{}]",loanRateQueryReq.getUserId());
        String tenantId = loanRateQueryReq.getTenantId();
        CmCustomerSecondLevel customer = customerService.getSecondLevelByCondition(loanRateQueryReq.getUserId(),
                loanRateQueryReq.getChannel(), tenantId, null);

        //获取产品信息
        PrProductTable product = productTableService.findProByProIdAndOrgId(loanRateQueryReq.getProductId(),
                customer.getOrganizationId(), tenantId);
        // 修改客户客群
        List<CmCustomerExtInfo> cmCustomerExtInfos = extCmCustomerExtInfoMapper.queryCustomerExtInfos(customer.getCustomerId(), tenantId, BizTypeProducts.getSymbolProductId(product.getProductId()));
        if (CollectionUtils.isNotEmpty(cmCustomerExtInfos)) {
            customer.setCustomerGroup(cmCustomerExtInfos.get(0).getCustomerGroup());
        }
        //获取机构信息
        PrOrganizationTable org = organizationTableService.findByOrId(customer.getOrganizationId(),
                tenantId);

        //规则获取利率id
        Map<String, Object> map = new HashMap<>();
        map.put(TransBizConstant.LOAN_RULE_TRANS_CHANNEL, loanRateQueryReq.getChannel());
        map.put(TransBizConstant.LOAN_RULE_CUS_IDENTIFY, customer.getCustomerGroup());

        RuleMatchReq ruleMatchReq = new RuleMatchReq(customer.getOrganizationId(), loanRateQueryReq.getProductId(),
                TransBizConstant.PRO_INTEREST_TABLE_ID, map, tenantId);
        String interestId =
                (String) aviatorService.executeRuleResultMap(ruleMatchReq).get(TransBizConstant.LOAN_RULE_RES_KEY);
        PrInterestTable interestTable = interestTableService.findInterestByInterestId(interestId, tenantId);

        //规则获取罚息id
        RuleMatchReq penaltyRuleMatchReq = new RuleMatchReq(customer.getOrganizationId(), loanRateQueryReq.getProductId(),
                TransBizConstant.PRO_PENALTY_TABLE_ID, map, tenantId);
        String penaltyId =(String) aviatorService.executeRuleResultMap(penaltyRuleMatchReq).get(TransBizConstant.LOAN_RULE_RES_KEY);
        //获取罚息参数信息
        PrPenaltyRateTable penaltyRateTable=prPenaltyRateTableService.findByPenaltyId(penaltyId,org.getOrganizationId(),org.getTenantId());

        //获取促销信息
        PromotionLabelBean promotionLabelBean = promotionService.matchingPromotion(tenantId,customer.getChannel(),customer.getCustomerId(),
                product.getProductId(),org.getNextProcessingDate());

        BigDecimal dayRate = interestTableService.getDailyRate(interestTable,org.getNextProcessingDate()).stripTrailingZeros();//日利率
        BigDecimal monthRate = interestTableService.getMonthRate(interestTable,org.getNextProcessingDate()).stripTrailingZeros();//月利率
        BigDecimal yearRate = interestTableService.getYearRate(interestTable).stripTrailingZeros(); //年利率

        loanRateQueryRes.setProductId(product.getProductId());//产品id
        loanRateQueryRes.setProductName(product.getChineseName());//产品名称

        if(null != promotionLabelBean){
            loanRateQueryRes.setHasPromotion(TransBizConstant.YES_FLAG);//是否有促销
            loanRateQueryRes.setPromotionDesc(promotionLabelBean.getPrPromotionInfo().getPromotionDesc());//促销描述
            loanRateQueryRes.setOriginalYearRate(yearRate);//原年利率
            loanRateQueryRes.setOriginalMonthRate(monthRate);//原月利率
            loanRateQueryRes.setOriginalDailyRate(dayRate);//原日利率
            Date effectiveDate = promotionLabelBean.getPrPromotionInfo().getEffectiveDate();
            Date expireDate = promotionLabelBean.getPrPromotionInfo().getExpireDate();
            if(effectiveDate.compareTo(promotionLabelBean.getCmCustomerLabel().getEffectiveDate())<0){
                effectiveDate=promotionLabelBean.getCmCustomerLabel().getEffectiveDate();
            }
            if(expireDate.compareTo(promotionLabelBean.getCmCustomerLabel().getExpireDate())>0){
                expireDate=promotionLabelBean.getCmCustomerLabel().getExpireDate();
            }
            loanRateQueryRes.setPromotionEffectiveDate(DateUtils.formatDate(effectiveDate));//生效时间
            loanRateQueryRes.setPromotionExpireDate(DateUtils.formatDate(expireDate));//失效时间


            //促销 使用促销参数从新计算
            if(TransBizConstant.PROMOTION_RATE_FIAG_1.equals(promotionLabelBean.getPrPromotionInfo().getRateFlag())){
                //按照折扣优惠
                loanRateQueryRes.setDailyRate(dayRate.multiply(promotionLabelBean.getPrPromotionInfo().getRateDiscountPercentage()));//日利率
                loanRateQueryRes.setMonthRate(monthRate.multiply(promotionLabelBean.getPrPromotionInfo().getRateDiscountPercentage()));//月利率
                loanRateQueryRes.setYearRate(yearRate.multiply(promotionLabelBean.getPrPromotionInfo().getRateDiscountPercentage()));//年利率
                loanRateQueryRes.setMonthBase(interestTableService.getMonthBase(interestTable.getMonthBase(),org.getNextProcessingDate()));//月利率计息基础
                loanRateQueryRes.setYearBase(interestTableService.getYearBase(interestTable.getYearBase()));//年利率计息基础
                //1 = 利率打折 利率打折与优惠券打折类似，逾期时利率上浮根据原始利率上浮
                loanRateQueryRes.setPenaltyDailyRate(penaltyRateTableService.getPenaltyDailyRate(dayRate,penaltyRateTable).stripTrailingZeros());//罚息日利率
                loanRateQueryRes.setPenaltyIncreaseNum(penaltyRateTable.getIncreaseNum().stripTrailingZeros());//罚息利率上浮数值
                loanRateQueryRes.setPenaltyIncreaseType(penaltyRateTable.getIncreaseType());//罚息利率上浮方式

            }else if(TransBizConstant.PROMOTION_RATE_FIAG_2.equals(promotionLabelBean.getPrPromotionInfo().getRateFlag())){
                //按照固定利率
                PrInterestTable proTable = interestTableService.findInterestByInterestId(promotionLabelBean.getPrPromotionInfo().getInterestTableId(), tenantId);

                BigDecimal promotionDayRate = interestTableService.getDailyRate(proTable,org.getNextProcessingDate()).stripTrailingZeros();//日利率
                BigDecimal promotionMonthRate = interestTableService.getMonthRate(proTable,org.getNextProcessingDate()).stripTrailingZeros();//月利率
                BigDecimal promotionYearRate = interestTableService.getYearRate(proTable).stripTrailingZeros(); //年利率

                loanRateQueryRes.setDailyRate(promotionDayRate);//日利率
                loanRateQueryRes.setMonthRate(promotionMonthRate);//月利率
                loanRateQueryRes.setYearRate(promotionYearRate);//年利率
                loanRateQueryRes.setMonthBase(interestTableService.getMonthBase(proTable.getMonthBase(),org.getNextProcessingDate()));//月利率计息基础
                loanRateQueryRes.setYearBase(interestTableService.getYearBase(proTable.getYearBase()));//年利率计息基础
                //罚息 2 = 固定利率 固定利率是使用此处配置的固定利率参数片，逾期时利率上浮根据此处配置的利率上浮
                loanRateQueryRes.setPenaltyDailyRate(penaltyRateTableService.getPenaltyDailyRate(promotionDayRate,penaltyRateTable).stripTrailingZeros());//罚息日利率
                loanRateQueryRes.setPenaltyIncreaseNum(penaltyRateTable.getIncreaseNum().stripTrailingZeros());//罚息利率上浮数值
                loanRateQueryRes.setPenaltyIncreaseType(penaltyRateTable.getIncreaseType());//罚息利率上浮方式

            }
        }else{
            //没有促销 按照原逻辑
            loanRateQueryRes.setHasPromotion(TransBizConstant.NO_FLAG);//是否有促销
            loanRateQueryRes.setDailyRate(dayRate);//日利率
            loanRateQueryRes.setMonthRate(monthRate);//月利率
            loanRateQueryRes.setYearRate(yearRate);//年利率
            loanRateQueryRes.setMonthBase(interestTableService.getMonthBase(interestTable.getMonthBase(),org.getNextProcessingDate()));//月利率计息基础
            loanRateQueryRes.setYearBase(interestTableService.getYearBase(interestTable.getYearBase()));//年利率计息基础

            loanRateQueryRes.setPenaltyDailyRate(penaltyRateTableService.getPenaltyDailyRate(dayRate,penaltyRateTable).stripTrailingZeros());//罚息日利率
            loanRateQueryRes.setPenaltyIncreaseNum(penaltyRateTable.getIncreaseNum().stripTrailingZeros());//罚息利率上浮数值
            loanRateQueryRes.setPenaltyIncreaseType(penaltyRateTable.getIncreaseType());//罚息利率上浮方式
        }

        //系统参数表信息
        SystemParameterRes systemParameterRes=systemParameterService.findByParamCode(TransBizConstant.LOAN_PRIME_RATE,org.getTenantId());
        loanRateQueryRes.setLoanPrimeRate(new BigDecimal(systemParameterRes.getParamValue()).stripTrailingZeros());//LPR利率

        return loanRateQueryRes;
    }


    @Override
    public MatchingAmortMethodRes matchingAmortMethodHandle(MatchingAmortMethodReq matchingAmortMethodReq) throws Exception {
        MatchingAmortMethodRes res = new MatchingAmortMethodRes();
        String userId = matchingAmortMethodReq.getUserId();
        String channel = matchingAmortMethodReq.getChannel();
        String tenantId = matchingAmortMethodReq.getTenantId();
        //验证客户是否存在
        logger.info("查询客户信息，客户id[{}]", userId);
        CmCustomerSecondLevel customer = customerService.getSecondLevelByCondition(userId,
                channel, tenantId, null);
        CmCustomerFirstLevel customerFirst = customerService.getFirstLevelByCondition(customer.getCustomerId(), customer.getOrganizationId(), customer.getTenantId());

        //获取产品信息
        PrProductTable product = productTableService.findProByProIdAndOrgId(matchingAmortMethodReq.getProductId(),
                customer.getOrganizationId(), tenantId);

        // 修改客户客群
        List<CmCustomerExtInfo> cmCustomerExtInfos = extCmCustomerExtInfoMapper.queryCustomerExtInfos(customer.getCustomerId(), tenantId, BizTypeProducts.getSymbolProductId(product.getProductId()));
        if (CollectionUtils.isNotEmpty(cmCustomerExtInfos)) {
            customer.setCustomerGroup(cmCustomerExtInfos.get(0).getCustomerGroup());
        }
        //获取机构信息
        PrOrganizationTable org = organizationTableService.findByOrId(customer.getOrganizationId(),
                tenantId);

        Map<String, Object> map = new HashMap<>();
        map.put(TransBizConstant.LOAN_RULE_TRANS_CHANNEL, channel);
        map.put(TransBizConstant.LOAN_RULE_TRANS_AMOUNT, matchingAmortMethodReq.getLoanAmount());
        map.put(TransBizConstant.LOAN_RULE_CUS_IDENTIFY, customer.getCustomerGroup());
        map.put(TransBizConstant.LOAN_RULE_CUSTOMER_LEVEL, customerFirst.getCustomerLevel());
        RuleMatchReq ruleMatchReq = new RuleMatchReq(org.getOrganizationId(), product.getProductId(),
                TransBizConstant.AMORT_METHOD_TABLE_ID, map, tenantId);
        List<Map<String, Object>> amortMethodIdList = aviatorService.executeRuleList(ruleMatchReq);

        //还款方式返回处理
        List<AmortMethodRes> amortMethodResList = new ArrayList<>();

        for(Map<String, Object> amortMap : amortMethodIdList){
            List<String> amortList = (List<String>) amortMap.get(TransBizConstant.LOAN_RULE_RES_KEY);

            List<PrAmortMethod>  amortMethodLists = amortMethodService.findAmortMethodByAmortMethodIdsAndTenId(amortList, org.getOrganizationId(), tenantId);
            //遍历还款方式并排除不属于本产品的还款方式
            amortMethodLists.stream().forEach(amortMethod -> {
                AmortMethodRes amortMethodRes = new AmortMethodRes();
                amortMethodRes.setAmortMethodId(amortMethod.getChargeOption());
                amortMethodRes.setAmortDescription(amortMethod.getDescription());
                amortMethodRes.setAllowTerms((String) amortMap.get(TransBizConstant.LOAN_RULE_AMORT_METHOD_KEY));
                amortMethodResList.add(amortMethodRes);
            });
        }

        res.setAmortMethodResList(amortMethodResList);
        return res;
    }

    /**
     * 规则获取产品
     *
     * @param loanElementQueryReq   机构ID
     * @return 产品id
     */
    private String getProductIdByRule(LoanElementQueryReq loanElementQueryReq, String orgId) throws TxnException {

        Map<String, Object> map = new HashMap<>();
        map.put(TransBizConstant.LOAN_RULE_TRANS_CHANNEL, loanElementQueryReq.getChannel());
        map.put(TransBizConstant.LOAN_RULE_PRODUCT_TYPE, loanElementQueryReq.getProductType());
        map.put(TransBizConstant.LOAN_RULE_MERCHANT_ID, loanElementQueryReq.getMerchantId());
        RuleMatchReq ruleMatchReq = new RuleMatchReq(orgId, null, TransBizConstant.PRO_MATCH_RULE_TYPE, map,
                loanElementQueryReq.getTenantId());
        return aviatorService.executeRuleResultMap(ruleMatchReq).get(TransBizConstant.LOAN_RULE_RES_KEY).toString();
    }


}
